package com.yanqu.road.utils.nline;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class NLineHelper {

    /**
     * 检查N * N 宫格，是个有连线。并返回连续编号。
     * @param board 棋盘
     * @return 连线编号数组
     * 水平线（从上到下）：1, 2, 3...
     * 垂直线（从左到右）：接着水平线编号，例如 4, 5, 6...
     * 对角线：紧接着垂直线编号，例如 7
     * 反对角线：接着对角线编号，例如 8
     */
    public static List<Integer> checkLines(int[][] board) {
        int n = board.length;
        List<Integer> lines = new ArrayList<>();

        // 检查水平线
        for (int i = 0; i < n; i++) {
            if (checkRow(board, i)) {
                lines.add(i + 1); // 水平线编号从1开始
            }
        }

        // 检查垂直线
        for (int j = 0; j < n; j++) {
            if (checkColumn(board, j)) {
                lines.add(n + j + 1); // 垂直线编号接着水平线
            }
        }

        // 检查对角线
        if (checkDiagonal(board)) {
            lines.add(2 * n + 1); // 对角线编号
        }

        // 检查反对角线
        if (checkAntiDiagonal(board)) {
            lines.add(2 * n + 2); // 反对角线编号
        }

        return lines; // 返回所有连线的编号列表
    }

    /**
     * 判断是否全部浇灌
     * @param board
     * @return
     */
    public static boolean checkAllComplete(int[][] board) {
        for (int[] row : board) {
            for (int element : row) {
                if (element != 1) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 获取没有完成的数量
     * @param board
     * @return
     */
    public static int checkNotCompleteNum(int[][] board) {
        int notNum = 0;
        for (int[] row : board) {
            for (int element : row) {
                if (element != 1) {
                    notNum++;
                }
            }
        }
        return notNum;
    }

    /**
     * 随机变更（0变1）
     * @param board 棋盘
     * @return 变更的坐标 arr[0] : 横坐标，arr[1] : 纵坐标
     */
    public static int[] changeRandomZerosToOne(int[][] board) {
        List<int[]> zeroPositions = new ArrayList<>();
        // 找出所有值为0的位置
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == 0) {
                    zeroPositions.add(new int[]{i, j});
                }
            }
        }

        // 随机选择0的位置变更为1
        int[] changedPosition = null;
        if (!zeroPositions.isEmpty()) {
            Random rand = new Random();
            changedPosition = zeroPositions.get(rand.nextInt(zeroPositions.size()));
            board[changedPosition[0]][changedPosition[1]] = 1;
        }
        return changedPosition;
    }

    /**
     * 变更指定坐标为1
     * @param board
     * @param x
     * @param y
     */
    public static void changeAppointToOne(int[][] board, int x, int y) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
               if (i == x && j == y) {
                   board[i][j] = 1;
                   break;
               }
            }
        }
    }

    private static boolean checkRow(int[][] board, int row) {
        for (int j = 1; j < board.length; j++) {
            if (board[row][j] != board[row][0] || board[row][0] != 1) {
                return false;
            }
        }
        return true;
    }

    private static boolean checkColumn(int[][] board, int col) {
        for (int i = 1; i < board.length; i++) {
            if (board[i][col] != board[0][col] || board[0][col] != 1) {
                return false;
            }
        }
        return true;
    }

    private static boolean checkDiagonal(int[][] board) {
        for (int i = 1; i < board.length; i++) {
            if (board[i][i] != board[0][0] || board[0][0] != 1) {
                return false;
            }
        }
        return true;
    }

    private static boolean checkAntiDiagonal(int[][] board) {
        int n = board.length;
        for (int i = 1; i < n; i++) {
            if (board[i][n - i - 1] != board[0][n - 1] || board[0][n - 1] != 1) {
                return false;
            }
        }
        return true;
    }
}
